package com.trip.order.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.trip.common.dto.OrderDTO;
import com.trip.common.entity.Driver;
import com.trip.common.entity.OrderInfo;
import com.trip.common.entity.TripOrder;
import com.trip.common.util.RedisUtil;
import com.trip.common.dto.LocationDto;
import com.trip.common.entity.TripOrder;
import com.trip.common.vo.DataDictionary;
import com.trip.common.vo.MyResultMap;
import com.trip.common.vo.Result;
import com.trip.order.mapper.TripOrderMapper;
import com.trip.order.service.OrderInfoService;
import com.trip.order.service.TripOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.trip.order.utils.IDWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;

import static com.trip.common.constant.OtherConstant.ORDER_HEAD;
import static com.trip.common.constant.RedisConstant.ORDER_WAITING_POOL;

import java.util.HashMap;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hr
 * @since 2024-09-05
 */
@Service
public class TripOrderServiceImpl extends ServiceImpl<TripOrderMapper, TripOrder> implements TripOrderService {

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private OrderInfoService orderInfoService;
    @Autowired(required = false)
    private TripOrderMapper orderMapper;

    @Override
    @Transactional
    public Result createOrder(OrderDTO orderDTO) {
        if(BeanUtil.isEmpty(orderDTO)) return Result.error("bean is null");
        // todo 判断用户是否有钱款
        /** 订单类型 -实时单/预约 */
        Integer orderType = orderDTO.getOrderType();
        //todo 预约到时发通知
        /** 出行类型id -快车/专车 */
        Integer tripTypeId = orderDTO.getTripTypeId();
        //todo 计算价格

        // 确保订单类型和出行类型不为 null
        if (orderType == null || tripTypeId == null) {
            return Result.error("orderType or tripTypeId is null");
        }

        if(checkOrder(orderDTO)) return Result.error("订单已存在,正在为您叫车...");

        try{
            //生成唯一订单编号
            orderDTO.setOrderNum(ORDER_HEAD+ IDWorker.onlyID());
            //保存order
            boolean savedOrder = this.save(orderDTO);
            OrderInfo orderInfo = orderDTO.getOrderInfo();
            if (orderInfo == null) {
                throw new RuntimeException("OrderInfo is null");
            }
            //保存orderInfo
            orderInfo.setOrderId(orderDTO.getOrderId());
            boolean savedOrderInfo = orderInfoService.save(orderInfo);

            if (!savedOrder || !savedOrderInfo) {
                throw new RuntimeException("System error");
            }
        }catch (Exception e){
            e.printStackTrace();
            return Result.error("fail create order");
        }
        //订单成功生成
       //todo 把订单加入到redis或者是mq

        return Result.ok("订单生成成功,正在为您叫车");
    }

    @Override
    @Transactional
    public Result updateOrder(OrderDTO orderDTO) {
        if(BeanUtil.isEmpty(orderDTO)) return Result.error("bean is null");
        if(BeanUtil.isEmpty(orderDTO.getOrderId())) return Result.error("id is null");
        try{
            OrderInfo orderInfo = orderDTO.getOrderInfo();
            if(BeanUtil.isNotEmpty(orderInfo)){
                //丢弃旧数据
                LambdaUpdateChainWrapper<OrderInfo> wrapper = orderInfoService.lambdaUpdate()
                        .set(OrderInfo::getDelFlag,1)
                        .set(OrderInfo::getStatus, 1)//1为旧数据
                        .eq(OrderInfo::getOrderId, orderInfo.getOrderId());
                boolean updateOld = orderInfoService.update(wrapper);
                orderInfo.setOrderInfoId(null);
                //添加新数据
                boolean saveNew = orderInfoService.save(orderInfo);
                if (!(saveNew && updateOld)) {
                    throw new RuntimeException("System error");
                }
                orderDTO.setOrderInfoId(orderInfo.getOrderInfoId());
            }
            //更新订单信息
            boolean update = this.updateById(orderDTO);
            if(!update) throw new RuntimeException("System error");
            // todo 通知司机订单改变
            return Result.ok("订单修改成功");
        }catch (Exception e){
            e.printStackTrace();
            return Result.error("fail update order");
        }
    }

    @Override
    @Transactional
    public Result receiverOrder(OrderDTO order) {
        if(BeanUtil.isEmpty(order)) return Result.error("bean is null");
        Long orderId = order.getOrderId();
        Driver driverId = order.getDriverId();
        if(BeanUtil.isEmpty(orderId)||BeanUtil.isEmpty(driverId)) return Result.error("error");
        //从redis中获取订单数据
        String key = ORDER_WAITING_POOL + orderId;
        OrderDTO orderDTO = JSON.parseObject(redisUtil.get(key), OrderDTO.class);
        if(BeanUtil.isEmpty(orderDTO)) return Result.error("手速慢了,被别人抢先了...");
        //上锁redis 数据库行锁 。。。
        try{
            //修改订单
            LambdaUpdateChainWrapper<TripOrder> wrapper = this.lambdaUpdate()
                    .set(TripOrder::getDriverId, driverId)
                    .set(TripOrder::getStatus, 2)
                    .eq(TripOrder::getOrderId, orderId)
                    .eq(TripOrder::getDelFlag, 0)
                    .eq(TripOrder::getStatus, 1);
            boolean update = this.update(wrapper);
            if(!update) return Result.error("抢单失败");
            //redis删除该订单
            redisUtil.del(key);
            //todo 修改司机状态
            //todo 通知用户
            //todo 记录司机接单记录
            return Result.ok("抢单成功");//返回订单信息，用户信息？
        }catch (Exception e){
            //redis重新添加订单
            return Result.error("抢单失败"+e.getMessage());
        }
    }

    private boolean checkOrder(OrderDTO order){
        if(BeanUtil.isEmpty(order)) return true;
        if(BeanUtil.isEmpty(order.getUserId())) return true;
        OrderInfo orderInfo = order.getOrderInfo();
        if(BeanUtil.isEmpty(orderInfo)) return true;
        //也可存redis
        try{
            int num = orderMapper.checkSameOrder(order);
            return num != 1;
        }catch (Exception e){
            e.printStackTrace();
            return true;
        }
    }

    @Override
    @Transactional
    public Result driverCancelOrder(OrderDTO order){
        //修改司机接单状态
        //修改订单状态
        //增加司机接单记录
        //扣除司机分数
        //redis添加订单
        return null;
    }

    @Override
    public boolean checkDriverReceiveOrder(Long driverId, Long orderId) {
        //redis中记录查询
        Long count = this.lambdaQuery()
                .eq(TripOrder::getOrderId, orderId)
                .eq(TripOrder::getDriverId, driverId)
                .in(TripOrder::getStatus, new Integer[] {2,3})
                .eq(TripOrder::getDelFlag, 0)
                .count();
        return count != 0;
    }

    private TripOrderMapper tripOrderMapper;

    @Override
    public Result getDriverAcceptOrder(LocationDto locationDto) {
        List<TripOrder> driverAcceptOrder = tripOrderMapper.getDriverAcceptOrder(locationDto);
        HashMap<String, Object> myResultMap = MyResultMap.getMyResultMap();
        myResultMap.put("data",driverAcceptOrder);
        if (driverAcceptOrder.size() > 0){
            return Result.ok("获取信息成功",myResultMap);
        }else {
            return Result.error(DataDictionary.FAIL,"当前没有订单");
        }
    }

}
